package easier.nested.scroll;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.NestedScrollingChild2;
import androidx.core.view.NestedScrollingChildHelper;
import androidx.core.view.NestedScrollingParent2;
import androidx.core.view.NestedScrollingParentHelper;
import androidx.core.view.ViewCompat;

/**
 * @author Liujin 2018-09-20:8:50
 */
public class TestNestedParentChildView extends FrameLayout implements NestedScrollingParent2,
    NestedScrollingChild2 {

    private static final String TAG = TestNestedParentChildView.class.getSimpleName();

    private NestedScrollingParentHelper mParentHelper;
    private NestedScrollingChildHelper mChildHelper;
    private int[] mConsumed = new int[2];

    public TestNestedParentChildView(
        @NonNull Context context ) {

        this( context, null, 0 );
    }

    public TestNestedParentChildView(
        @NonNull Context context,
        @Nullable AttributeSet attrs ) {

        this( context, attrs, 0 );
    }

    public TestNestedParentChildView(
        @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr ) {

        super( context, attrs, defStyleAttr );
        init();
    }

    private void init() {

        mParentHelper = new NestedScrollingParentHelper( this );
        mChildHelper = new NestedScrollingChildHelper( this );
        setNestedScrollingEnabled( true );
    }

    // ========================= parent =========================

    @Override
    public boolean onStartNestedScroll(
        @NonNull View child, @NonNull View target, int axes, int type ) {

        return true;
    }

    @Override
    public void onNestedScrollAccepted(
        @NonNull View child, @NonNull View target, int axes, int type ) {

        mParentHelper.onNestedScrollAccepted( child, target, axes, type );
    }

    @Override
    public void onStopNestedScroll( @NonNull View target, int type ) {

        mParentHelper.onStopNestedScroll( target, type );
    }

    @Override
    public void onNestedScroll(
        @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed,
        int type ) {

    }

    @Override
    public void onNestedPreScroll(
        @NonNull View target, int dx, int dy, @NonNull int[] consumed, int type ) {

        int offsetX = 0;
        int offsetY = 0;

        if ( dx > 0 ) {
            int finalX = target.getRight() + dx;
            if ( finalX > getWidth() ) {
                offsetX = finalX - getWidth();
            }
        } else {
            int finalX = target.getLeft() + dx;
            if ( finalX < 0 ) {
                offsetX = finalX;
            }
        }

        if ( dy > 0 ) {
            int finalY = target.getBottom() + dy;
            if ( finalY > getHeight() ) {
                offsetY = finalY - getHeight();
            }
        } else {

            int finalY = target.getTop() + dy;
            if ( finalY < 0 ) {
                offsetY = finalY;
            }
        }

        consumed[0] = offsetX;
        consumed[1] = offsetY;

        if ( offsetX != 0 || offsetY != 0 ) {
            startNestedScroll(
                ViewCompat.SCROLL_AXIS_HORIZONTAL | ViewCompat.SCROLL_AXIS_VERTICAL,
                ViewCompat.TYPE_TOUCH
            );

            dispatchNestedPreScroll(
                offsetX,
                offsetY,
                mConsumed,
                null,
                ViewCompat.TYPE_TOUCH
            );
            offsetX -= mConsumed[0];
            offsetY -= mConsumed[1];

            stopNestedScroll( ViewCompat.TYPE_TOUCH );
        }

        offsetLeftAndRight( offsetX );
        offsetTopAndBottom( offsetY );
    }

    // ========================= child =========================

    @Override
    public void setNestedScrollingEnabled( boolean enabled ) {

        super.setNestedScrollingEnabled( enabled );
        mChildHelper.setNestedScrollingEnabled( enabled );
    }

    @Override
    public boolean isNestedScrollingEnabled() {

        return mChildHelper.isNestedScrollingEnabled();
    }

    @Override
    public boolean startNestedScroll( int axes, int type ) {

        return mChildHelper.startNestedScroll( axes, type );
    }

    @Override
    public void stopNestedScroll( int type ) {

        mChildHelper.stopNestedScroll( type );
    }

    @Override
    public boolean hasNestedScrollingParent( int type ) {

        return mChildHelper.hasNestedScrollingParent( type );
    }

    @Override
    public boolean dispatchNestedScroll(
        int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed,
        @Nullable int[] offsetInWindow, int type ) {

        return mChildHelper
            .dispatchNestedScroll( dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,
                offsetInWindow, type
            );
    }

    @Override
    public boolean dispatchNestedPreScroll(
        int dx, int dy, @Nullable int[] consumed, @Nullable int[] offsetInWindow, int type ) {

        return mChildHelper.dispatchNestedPreScroll( dx, dy, consumed, offsetInWindow, type );
    }
}
